﻿// main.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "../public/load_mb.h"
#include "../public/xpackSupports.h"
#include "../wke.h"

#include <exprtk.hpp>
#include <filesystem>
#include <iostream>
#include <string>
#include <vector>
#include <xpack/json.h>

void WKE_CALL_TYPE onWindowDestroy(wkeWebView, void *);

jsValue WKE_CALL_TYPE jsSetWindowTitle(jsExecState es, void *vptr);
jsValue WKE_CALL_TYPE jsOptionAlert(jsExecState es, void *vptr);
jsValue WKE_CALL_TYPE jsCalculteExpression(jsExecState es, void *vptr);
jsValue WKE_CALL_TYPE jsGetTableData(jsExecState es, void *vptr);

int main()
{
    auto pathDll = load_mb();
    if (pathDll.empty())
        return 1;
    auto pathRoot = pathDll;
    pathRoot.remove_filename();

    auto window = wkeCreateWebWindow(WKE_WINDOW_TYPE_POPUP, nullptr, 0, 0, 640, 480);
    if (!window)
    {
        return 1;
    }
    auto mainPageUrl = pathRoot / "resource" / "menu.html";
    if (!std::filesystem::exists(mainPageUrl))
    {
        return 1;
    }

    auto hwnd = wkeGetWindowHandle(window);
    wkeSetWindowTitleW(window, L"看到这个就说明前端没有设置标题");
    wkeSetCspCheckEnable(window, false);
    wkeLoadURLW(window, mainPageUrl.wstring().c_str());
    wkeOnWindowDestroy(window, onWindowDestroy, nullptr);
    wkeJsBindFunction("setWindowTitle", jsSetWindowTitle, window, 1);
    wkeJsBindFunction("optionAlert", jsOptionAlert, hwnd, 1);
    wkeJsBindFunction("calculateExpression", jsCalculteExpression, nullptr, 1);
    wkeJsBindFunction("getTableData", jsGetTableData, nullptr, 0);

    wkeMoveToCenter(window);
    wkeShowWindow(window, true);

    MSG msg = {0};
    while (GetMessageW(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessageW(&msg);
        if (msg.message == WM_CLOSE)
            break;
    }

    wkeFinalize();
    return 0;
}

void WKE_CALL_TYPE onWindowDestroy(wkeWebView, void *)
{
    PostMessage(nullptr, WM_CLOSE, 0, 0);
}

jsValue WKE_CALL_TYPE jsSetWindowTitle(jsExecState es, void *vptr)
{
    if (jsArgCount(es) != 1)
        return jsUndefined();
    auto value = jsArg(es, 0);
    auto type = jsTypeOf(value);
    if (!jsIsString(value))
        return jsUndefined();
    auto window = static_cast<wkeWebView>(vptr);
    const auto *szTitle = jsToTempString(es, value);
    wkeSetWindowTitle(window, szTitle);
    return jsUndefined();
}

jsValue WKE_CALL_TYPE jsOptionAlert(jsExecState es, void *vptr)
{
    if (jsArgCount(es) != 1)
        return jsUndefined();
    auto value = jsArg(es, 0);
    auto type = jsTypeOf(value);
    if (!jsIsString(value))
        return jsUndefined();
    const auto *szTitle = jsToTempString(es, value);
    auto hwnd = static_cast<HWND>(vptr);
    MessageBoxA(hwnd, szTitle, "alert", MB_OK);
    return jsUndefined();
}

jsValue WKE_CALL_TYPE jsCalculteExpression(jsExecState es, void *)
{
    if (jsArgCount(es) != 1)
        return jsUndefined();
    auto value = jsArg(es, 0);
    auto type = jsTypeOf(value);
    if (!jsIsString(value))
        return jsUndefined();
    const auto *szExpression = jsToTempString(es, value);

    using symbol_table = exprtk::symbol_table<double>;
    using expression = exprtk::expression<double>;
    using parser = exprtk::parser<double>;

    symbol_table table;
    table.add_constants();
    expression exp;
    exp.register_symbol_table(table);
    parser p;
    if (p.compile(szExpression, exp))
    {
        const double dbValue = exp.value();

        return jsDouble(dbValue);
    }
    else
    {
        return jsString(es, p.error().c_str());
    }
}

struct TableData
{
    std::wstring QLRMC;
    std::wstring ZJH;
    int XB;

    XPACK(M(QLRMC, ZJH, XB));
};

jsValue WKE_CALL_TYPE jsGetTableData(jsExecState es, void *vptr)
{
    static const std::vector<TableData> data{
        {L"张三", L"123456", 1},
        {L"李四", L"456789", 1},
        {L"王五", L"789123", 2},
    };
    static const std::string json = xpack::json::encode(data);
    return jsString(es, json.c_str());
}
